<?php

namespace App\Console\Commands;

use App\Models\Base\LogEverydayData;
use App\Models\Base\ServerList;
use App\Service\AccountService;
use App\Service\ChannelService;
use App\Service\OrderService;
use App\Service\PlayerService;
use App\Service\ServerService;
use Illuminate\Support\Facades\Log;

class FetchDataList extends CommandBase
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'fetch:dataList {dateTime?}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '基础数据统计';

    protected $model;

    /**
     * Create a new command instance.
     */
    public function __construct()
    {
        parent::__construct();
        $this->model = new LogEverydayData();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $dateTime = $this->argument('dateTime');
        if ($dateTime) {
            $this->today = $dateTime;
            $this->todayTimestamp = strtotime($dateTime);
            $this->yesterdayTimestamp = $this->todayTimestamp - 86400;
            $this->yesterday = date('Y-m-d', $this->yesterdayTimestamp);
        }

        try {
//            全平台统计
            $this->performStatistical();
            $this->model->save();
            $this->model = null;
            echo 'perform:success';

            //渠道统计
            $this->channelStat();
            echo 'channel:success';

            //区服统计
            $this->serverStat();
            echo 'server:success';

            //区服渠道交叉统计
            $this->serverChannelStat();
        } catch (\Exception $e) {
            Log::error('统计基础数据错误'.$e->getMessage());
            dd($e);
        }
    }

    /**
     * 区服下渠道统计
     */
    protected function serverChannelStat()
    {
        $serverIds = ServerList::all()->pluck('server_id');
        $channelIds = ChannelService::getChannelIds();
        if ($serverIds->isEmpty() || empty($channelIds)) {
            return false;
        }
        foreach ($serverIds as $serverId) {
            setDB($serverId);
            foreach ($channelIds as $channel_value) {
                $channel_no = $channel_value['channel_no'];
                $platform_id = $channel_value['pid'];
                $this->model = new LogEverydayData();
                $this->model->server_id = $serverId;
                $this->model->channel_id = $channel_no;
                $this->model->platform_id = $platform_id;
                $this->model->type = self::STAT_TYPE_SERVER_CHANNEL;
                //新增角色数量
                $new_role = PlayerService::getSignPlayer($this->yesterdayTimestamp, $this->todayTimestamp, $channel_no);
                $this->model->new_role_num = $new_role->count();
                //登录人数
                $login_number = PlayerService::sometimeLoginPlayer($this->yesterdayTimestamp,
                    $this->todayTimestamp, $channel_no)->count();
                $this->model->login_player_num = $login_number;
                //昨日订单金额
                $order_amount = OrderService::getDayOrderAmount($this->yesterdayTimestamp, $this->todayTimestamp, $serverId, $channel_no);
                $this->model->amount = $order_amount;
                //付费人数
                $pay_player_num = OrderService::payPlayerNum($this->yesterdayTimestamp, $this->todayTimestamp, $serverId, $channel_no);
                $this->model->pay_player_num = $pay_player_num;
                //付费率
                $this->model->pay_player_ratio = $login_number ? floatPercent($pay_player_num / $login_number) : 0;
                $this->model->arpu = $login_number ? round($order_amount / $login_number, 2) : 0;
                $this->model->arppu = $pay_player_num ? round($order_amount / $pay_player_num, 2) : 0;
                $this->model->date_time = $this->yesterday;
                $this->model->amount = $order_amount;
                $this->model->pay_player_num = $pay_player_num;
                $this->model->active_arpu = $login_number ? $order_amount / $login_number : 0;
                $new_role_ids = $new_role->pluck('id');
                //新用户付费金额和人数
                $this->newUserPayStat($new_role_ids);
                //老用户付费金额和人数
                $this->oldUserPayStat($new_role_ids->all(), $channel_no, $serverId);
                $this->model->save();
                $this->model = null;
            }
        }
    }

    /**
     * 区服数据统计
     */
    protected function serverStat()
    {
        $server = ServerList::all()->pluck('server_id');
        foreach ($server as $server_id) {
            setDB($server_id);
            $this->model = new LogEverydayData();
            $this->model->server_id = $server_id;
            $this->model->type = self::STAT_TYPE_SERVER;
            //新增角色数量
            $new_role = PlayerService::getSignPlayer($this->yesterdayTimestamp, $this->todayTimestamp);
            $this->model->new_role_num = $new_role->count();
            //登录人数
            $login_number = PlayerService::sometimeLoginPlayer($this->yesterdayTimestamp, $this->todayTimestamp)->count();
            $this->model->login_player_num = $login_number;
            //昨日订单金额
            $order_amount = OrderService::getDayOrderAmount($this->yesterdayTimestamp, $this->todayTimestamp, $server_id);
            $this->model->amount = $order_amount;
            //付费人数
            $pay_player_num = OrderService::payPlayerNum($this->yesterdayTimestamp, $this->todayTimestamp, $server_id);
            $this->model->pay_player_num = $pay_player_num;

            //付费率
            $this->model->pay_player_ratio = $login_number ? floatPercent($pay_player_num / $login_number) : 0;
            //在线统计
            $this->serverRoleOnline($server_id);
            $this->model->arpu = $login_number ? round($order_amount / $login_number, 2) : 0;
            $this->model->arppu = $pay_player_num ? round($order_amount / $pay_player_num, 2) : 0;
            $this->model->date_time = $this->yesterday;
            $this->model->amount = $order_amount;
            $this->model->pay_player_num = $pay_player_num;
            $this->model->active_arpu = $login_number ? $order_amount / $login_number : 0;

            $new_role_ids = $new_role->pluck('id');
            //新用户付费金额和人数
            $this->newUserPayStat($new_role_ids);
            //老用户付费金额和人数
            $this->oldUserPayStat($new_role_ids->all(), null, $server_id);
            $this->model->save();
            $this->model = null;
        }
    }

    /**
     * 渠道统计
     */
    protected function channelStat()
    {
        //获取所有渠道

        $channelIds = ChannelService::getChannelIds();
        if (empty($channelIds)) {
            return false;
        }
        foreach ($channelIds as $channel_value) {
            $channel_no = $channel_value['channel_no'];
            $platform_id = $channel_value['pid'];
            $this->model = new LogEverydayData();
            $this->model->channel_id = $channel_no;
            $this->model->platform_id = $platform_id;
            $this->model->type = self::STAT_TYPE_CHANNEL;
            //昨日注册人数
            $users = ChannelService::registerUsers($this->yesterdayTimestamp, $this->todayTimestamp, $channel_no);
            $this->model->new_player_num = $users->count();

            //昨日登录人数
            $login_player_num = ChannelService::LoginUsers($this->yesterdayTimestamp,
                $this->todayTimestamp, $channel_no);
            //昨日订单金额
            $amount = OrderService::getDayOrderAmount($this->yesterdayTimestamp, $this->todayTimestamp,
                null, $channel_no);
            //付费人数
            $pay_player_num = OrderService::payPlayerNum($this->yesterdayTimestamp, $this->todayTimestamp,
                null, $channel_no);
            //付费率
            $this->model->pay_player_ratio = $login_player_num ?
                floatPercent($pay_player_num / $login_player_num) : 0;

            //新增角色
            $this->model->new_role_num =  $this->newRolesNumber($channel_no);
            $this->model->arpu = $login_player_num ? round($amount / $login_player_num, 2) : 0;
            $this->model->arppu = $pay_player_num ? round($amount / $pay_player_num, 2) : 0;
            $this->model->date_time = $this->yesterday;
            $this->model->amount = $amount;
            $this->model->login_player_num = $login_player_num;
            $this->model->pay_player_num = $pay_player_num;
            $this->model->active_arpu = $login_player_num ? $amount / $login_player_num : 0;
            $new_account_ids = $users->pluck('ac_id');

            //新用户充值统计
            $this->newUserPayStat($new_account_ids, $channel_no);
            //老用户付费金额和人数
            $this->oldUserPayStat($new_account_ids->all(), $channel_no);

            $this->model->save();
            $this->model = null;
        }
    }

    /**
     * 执行全服数据统计.
     */
    protected function performStatistical()
    {
        $this->model->type = self::STAT_TYPE_PLATFORM;
        //昨日注册人数
        $new_users = AccountService::signNumber($this->yesterdayTimestamp, $this->todayTimestamp);
        $this->model->new_player_num = $new_users->count();
        //昨日登录人数
        $player_num = AccountService::loginNumber($this->yesterdayTimestamp, $this->todayTimestamp)->count();

        //昨日订单金额
        $order_amount = OrderService::getDayOrderAmount($this->yesterdayTimestamp, $this->todayTimestamp);
        //付费人数
        $pay_player_num = OrderService::payPlayerNum($this->yesterdayTimestamp, $this->todayTimestamp);
        //付费率
        $this->model->pay_player_ratio = $player_num ? floatPercent($pay_player_num / $player_num) : 0;

        //用户在线统计
        $this->roleOnline();
        $this->model->new_role_num = $this->newRolesNumber();
        $this->model->arpu = $player_num ? round($order_amount / $player_num, 2) : 0;
        $this->model->arppu = $pay_player_num ? round($order_amount / $pay_player_num, 2) : 0;
        $this->model->date_time = $this->yesterday;
        $this->model->amount = $order_amount;
        $this->model->login_player_num = $player_num;
        $this->model->pay_player_num = $pay_player_num;
        $this->model->active_arpu = $order_amount / $player_num;
        $new_account_ids = $new_users->pluck('ac_id');
        //新用户付费金额和人数
        $this->newUserPayStat($new_account_ids);
        //老用户付费金额和人数
        $this->oldUserPayStat($new_account_ids->all());
    }

    /**
     * 老用户充值统计.
     *
     * @param array $new_account_ids 新用户ID集合
     */
    protected function oldUserPayStat(array $new_account_ids, $channel_id = null, $server_id = null)
    {
        $ids = arrayNumericString($new_account_ids);
        $orders = OrderService::getNotUserOrders($ids, $this->yesterdayTimestamp, $this->todayTimestamp, $channel_id, $server_id);
        if ($orders->isEmpty()) {
            $this->model->old_player_pay_num = $this->model->old_player_amount = 0;
        } else {
            $this->model->old_player_pay_num = $orders->pluck('userid')->unique()->count();
            $this->model->old_player_amount = $orders->sum('amount');
        }
    }

    /**
     * 新用户充值统计.
     *
     * @param array $new_account_ids 用户ID集合
     */
    protected function newUserPayStat($new_account_ids, $channel_id = null)
    {
        if ($new_account_ids->isEmpty()) {
            $this->model->new_player_pay_num = $this->model->new_player_amount = $this->model->new_player_ltv = 0;
        } else {
            $ids = arrayNumericString($new_account_ids->all());
            $orders = OrderService::getUserOrders($ids, $this->yesterdayTimestamp, $this->todayTimestamp, $channel_id);
            if ($orders->isEmpty()) {
                $this->model->new_player_pay_num = $this->model->new_player_amount = $this->model->new_player_ltv = 0;
            } else {
                $this->model->new_player_amount = $orders->sum('amount');
                $this->model->new_player_pay_num = $orders->pluck('userid')->unique()->count();
                $this->model->new_player_ltv = $this->model->new_player_amount / $this->model->new_player_num;
            }
        }
    }

    /**
     * 玩家在线统计.
     */
    protected function roleOnline()
    {
        //最高,最低,平均在线
        $user_number = AccountService::topTime($this->yesterday);
        if ($user_number->isEmpty()) {
            $this->model->online_max_num = $this->model->online_min_num = $this->model->online_avg_num = 0;
        } else {
            $this->model->online_max_num = $user_number->max()->numbers;
            $this->model->online_min_num = $user_number->min()->numbers;
            $hour_number = $user_number->count();
            $user_counts = $user_number->pluck('numbers')->sum();
            $this->model->online_avg_num = ceil($user_counts / $hour_number);
        }
    }

    /**
     * 昨日新增角色数量.
     *
     * @return int
     */
    protected function newRolesNumber($channel_id=null)
    {
        $role_numbers = 0;
        $server_ids = ServerService::serverIds();
        foreach ($server_ids as $server_id) {
            setDB($server_id);
            $number = PlayerService::getSignPlayer($this->yesterdayTimestamp, $this->todayTimestamp,$channel_id)->count();
            $role_numbers += $number;
        }

        return $role_numbers;
    }

    /**
     * 玩家在线统计.
     *
     * @param int $server_id
     */
    protected function serverRoleOnline($server_id)
    {
        //最高,最低,平均在线
        $user_number = PlayerService::onlineNumber($this->yesterday, $server_id);
        if ($user_number->isEmpty()) {
            $this->model->online_max_num = $this->model->online_min_num = $this->model->online_avg_num = 0;
        } else {
            $this->model->online_max_num = $user_number->max()->numbers;
            $this->model->online_min_num = $user_number->min()->numbers;
            $hour_number = $user_number->count();
            $user_counts = $user_number->pluck('numbers')->sum();
            $this->model->online_avg_num = ceil($user_counts / $hour_number);
        }
    }
}
